home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / X11R4 / cmds / X / ddx / dec / qvss / qvss_io.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-12-17  |  25.4 KB  |  1,130 lines

  1. /***********************************************************
  2. Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts,
  3. and the Massachusetts Institute of Technology, Cambridge, Massachusetts.
  4.  
  5.                         All Rights Reserved
  6.  
  7. Permission to use, copy, modify, and distribute this software and its 
  8. documentation for any purpose and without fee is hereby granted, 
  9. provided that the above copyright notice appear in all copies and that
  10. both that copyright notice and this permission notice appear in 
  11. supporting documentation, and that the names of Digital or MIT not be
  12. used in advertising or publicity pertaining to distribution of the
  13. software without specific, written prior permission.  
  14.  
  15. DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
  16. ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
  17. DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
  18. ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  19. WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
  20. ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  21. SOFTWARE.
  22.  
  23. ******************************************************************/
  24. /* $XConsortium: qvss_io.c,v 1.101 89/12/16 20:35:19 rws Exp $ */
  25.  
  26. #include <stdio.h>
  27. #include <sys/types.h>
  28. #include <sys/file.h>
  29. #include <sys/time.h>
  30. #include <vaxuba/qvioctl.h>
  31. #include <errno.h>
  32.  
  33. #include "X.h"
  34. #define  NEED_EVENTS
  35. #include "Xproto.h"
  36. #include "scrnintstr.h"
  37. #include "cursorstr.h"
  38. #include "pixmap.h"
  39. #include "input.h"
  40. #include "windowstr.h"
  41. #include "regionstr.h"
  42. #include "resource.h"
  43.  
  44. #include "mfb.h"
  45. #include "mi.h"
  46.  
  47. static Bool qvRealizeCursor(), qvUnrealizeCursor(), qvDisplayCursor();
  48. static Bool qvSetCursorPosition();
  49. static void qvCursorLimits();
  50. static void qvPointerNonInterestBox();
  51. static void qvConstrainCursor();
  52. static void qvQueryBestSize();
  53. void qvResolveColor();
  54. Bool qvCreateColormap();
  55. void qvDestroyColormap();
  56.  
  57. extern void miRecolorCursor();
  58. static int  qvGetMotionEvents();
  59. static void qvChangePointerControl(), qvChangeKeyboardControl(), qvBell();
  60. extern Bool mfbScreenInit();
  61.  
  62. extern int monitorResolution;
  63.  
  64. extern int errno;
  65.  
  66. /*
  67.  * Ultrix 3.0 uses new names for everything!
  68.  */
  69. #ifdef _QVEVENT_
  70. # define ULTRIX3_0
  71. #endif
  72.  
  73. #ifdef ULTRIX3_0
  74. /*
  75.  * the stuff below makes this code work on
  76.  * both qv and sm drivers under Ultrix 3.0 (ne 2.4)
  77.  */
  78.  
  79. /* XXX WARNING!!! This kludge assumes that
  80.  * the event/cursor/box structures are identical
  81.  * in size for both qv and sm.  If they change
  82.  * radically, get help
  83.  */
  84.  
  85. #undef QIOCGINFO
  86. #undef QIOCSMSTATE
  87. #undef QIOCINIT
  88. #undef QIOCKPCMD
  89. #undef QIOCADDR
  90. #undef QIOWCURSOR
  91. #undef QIOKERNLOOP
  92. #undef QIOKERNUNLOOP
  93. #undef QIODISPON
  94. #undef QIOVIDEOON    
  95. #undef QIODISPOFF
  96. #undef QIOVIDEOOFF
  97. #undef QD_KERN_UNLOOP
  98. #undef HOLD
  99.  
  100. #define mouse_report    bogus_mouse_report
  101. #define _event        sm_event
  102. #define _timecoord    sm_timecoord
  103. #define _eventqueue    sm_eventqueue
  104. #define _cursor        sm_cursor
  105. #define _box        sm_box
  106.  
  107. # include    <vaxuba/smioctl.h>
  108.  
  109. #undef mouse_report
  110. #undef _event
  111. #undef _timecoord
  112. #undef _eventqueue
  113. #undef _cursor
  114. #undef _box
  115.  
  116. static Bool        isSMdevice;
  117. static struct sm_info    *smInfo;
  118. static struct qv_info    *qvInfo;
  119.  
  120. /*
  121.  * magic defines to make the code below less
  122.  * ugly
  123.  */
  124. # define vsEventQueue    qvEventQueue
  125. # define vsCursor    qvCursor
  126. # define vsEvent    qvEvent
  127. # define vsTimeCoord    qvTimeCoord
  128. # define vsBox        qvBox
  129. # define head        eHead
  130. # define tail        eTail
  131. # define size        eSize
  132. # define vse_x        x
  133. # define vse_y        y
  134. # define vse_time    time
  135. # define vse_type    type
  136. # define vse_device    device
  137. # define vse_key    key
  138. # define vse_direction    direction
  139. # define VSE_KBTDOWN    QV_KBTDOWN
  140. # define VSE_KBTUP    QV_KBTUP
  141. # define VSE_KBTRAW    QV_KBTRAW
  142. # define VSE_BUTTON    QV_BUTTON
  143.  
  144. #else
  145. static struct qv_info    *qvInfo;
  146. #endif
  147.  
  148. static vsEventQueue    *queue;
  149. static vsBox        *mbox;
  150. static vsCursor        *mouse;
  151.  
  152. static int        fdQVSS;
  153. static int        qLimit;
  154. static int        lastEventTime;
  155. static DevicePtr    qvKeyboard;
  156. static DevicePtr    qvPointer;
  157. static int              hotX, hotY;
  158. static BoxRec           constraintBox;
  159.  
  160. static Bool        (*CloseScreen)();
  161.  
  162. #define MAX_LED 3  /* only 3 LED's can be set by user; Lock LED is controlled by server */
  163.  
  164. /* ARGSUSED */
  165. static Bool qvssSaveScreen(pScreen, on)
  166.     ScreenPtr pScreen;
  167.     int on;
  168. {
  169.     if (on != SCREEN_SAVER_ON)
  170.     {
  171.         lastEventTime = GetTimeInMillis();    
  172. #ifdef QIOVIDEOON
  173.     (void) ioctl(fdQVSS, QIOVIDEOON, (char *)NULL);
  174. #endif
  175.     return TRUE;
  176.     }
  177.     else
  178.     {
  179. #ifdef QIOVIDEOOFF
  180.     (void) ioctl(fdQVSS, QIOVIDEOOFF, (char *)NULL);
  181.     return TRUE;
  182. #else
  183.         return FALSE;
  184. #endif
  185.     }
  186. }
  187.  
  188. /* ARGSUSED */
  189. static Bool
  190. qvssScreenClose(index, pScreen)
  191.     int index;
  192.     ScreenPtr pScreen;
  193. {
  194.     /* This routine frees all of the dynamically allocated space associate
  195.     with a screen. */
  196.  
  197.     (*CloseScreen) (index, pScreen);
  198.  
  199.     if(close(fdQVSS))
  200.     {
  201.     ErrorF("Closing QVSS yielded %d\n", errno);
  202.     return (FALSE);
  203.     }
  204.     return (TRUE);
  205. }
  206.  
  207.  
  208. static
  209. qvssPixelError(index)
  210.     int    index;
  211. {
  212.     ErrorF("Only 0 or 1 are acceptable pixels for device %d\n", index);
  213. }
  214.  
  215.  
  216. Bool
  217. qvssScreenInit(index, pScreen, argc, argv)
  218.     int index;
  219.     ScreenPtr pScreen;
  220.     int argc;        /* these two may NOT be changed */
  221.     char **argv;
  222. {
  223.     Bool        retval, SpecificB, SpecificW;
  224.     ColormapPtr        pColormap;
  225.     VisualPtr        pVisual;
  226.     int            i;
  227.     char        *blackValue, *whiteValue;
  228.  
  229.     if ((fdQVSS = open("/dev/mouse", O_RDWR | O_NDELAY, 0)) <  0)
  230.     {
  231.     ErrorF(  "couldn't open qvss \n");
  232.     return FALSE; 
  233.     }
  234.     /* force an init to get the scrollmap right */
  235.     ioctl(fdQVSS, QIOCINIT, (char *)NULL);
  236.     if (ioctl(fdQVSS, QIOCADDR, (char *)&qvInfo) < 0)
  237.     {
  238.     ErrorF(  "error getting address of QVSS \n");
  239.     close(fdQVSS);
  240.     return FALSE;
  241.     }
  242. #ifdef ULTRIX3_0
  243.     /*
  244.      * test to see if we're using the sm driver instead
  245.      */
  246.     isSMdevice = FALSE;
  247.     if ((char *) 0 <= qvInfo->bitmap && qvInfo->bitmap <= (char *) 0x7fffffff) {
  248.         smInfo = (struct sm_info *) qvInfo;
  249.     isSMdevice = TRUE;
  250.     }
  251. #endif
  252.  
  253. #ifdef ULTRIX3_0
  254.     if (isSMdevice) {
  255.         mouse = (vsCursor *) &smInfo->mouse;
  256.     mbox = (vsBox *) &smInfo->mbox;
  257.     queue = (vsEventQueue *) &smInfo->qe;
  258.     } else
  259. #endif
  260.     {
  261.     mouse = (vsCursor *) &qvInfo->mouse;
  262.     mbox = (vsBox *) &qvInfo->mbox;
  263.     mbox->bottom = 0; /* trash pointer non-interest box 'cause driver won't */
  264. #ifdef ULTRIX3_0
  265.     queue = &qvInfo->qe;
  266. #else
  267.     /*
  268.        the following hack is really pretending a part of one record
  269.        is really a record of another type!
  270.         */
  271.     queue = (vsEventQueue *) &qvInfo->ibuff;
  272. #endif
  273.     }
  274.     qLimit = queue->size - 1;
  275.  
  276.     i = monitorResolution ? monitorResolution : 80;
  277.  
  278.     blackValue = NULL;
  279.     SpecificB = FALSE;
  280.     whiteValue = NULL;
  281.     SpecificW = FALSE;
  282.     for(i = 1; i < argc; i++)
  283.     {
  284.     if(strncmp(argv[i], "-bp:", 4) == 0 && atoi(argv[i] + 4) == index)
  285.     {
  286.         if(++i < argc)
  287.         {
  288.         blackValue = argv[i];
  289.         SpecificB = TRUE;
  290.         }
  291.         else
  292.         UseMsg();
  293.     }
  294.     if(strncmp(argv[i], "-wp:", 4) == 0 && atoi(argv[i] + 4) == index)
  295.     {
  296.         if(++i < argc)
  297.         {
  298.         whiteValue = argv[i];
  299.         SpecificW = TRUE;
  300.         }
  301.         else
  302.         UseMsg();
  303.     }
  304.     if(strcmp(argv[i], "-bp") == 0 && !SpecificB)
  305.     {
  306.         if(++i < argc)
  307.         {
  308.         blackValue = argv[i];
  309.         }
  310.         else
  311.         UseMsg();
  312.     }
  313.     if(strcmp(argv[i], "-wp") == 0 && !SpecificW)
  314.     {
  315.         if(++i < argc)
  316.         {
  317.         whiteValue = argv[i];
  318.         }
  319.         else
  320.         UseMsg();
  321.     }
  322.         
  323.     }
  324.     pScreen->blackPixel = 0;
  325.     pScreen->whitePixel = 1;
  326.     if(blackValue)
  327.     {
  328.     if((i = atoi(blackValue)) == 0 || i == 1)
  329.         pScreen->blackPixel = i;
  330.     else  
  331.         qvssPixelError(index);
  332.     }
  333.     if(whiteValue)
  334.     {
  335.         if((i = atoi(whiteValue)) == 0 || i == 1)
  336.             pScreen->whitePixel = i;
  337.         else  
  338.         qvssPixelError(index);
  339.     }
  340.  
  341.     /*
  342.      * qv screen saver
  343.      */
  344.     pScreen->SaveScreen = qvssSaveScreen;
  345.     /*
  346.      * qv cursor routines
  347.      */
  348.     pScreen->RealizeCursor = qvRealizeCursor;
  349.     pScreen->UnrealizeCursor = qvUnrealizeCursor;
  350.     pScreen->DisplayCursor = qvDisplayCursor;
  351.     pScreen->SetCursorPosition = qvSetCursorPosition;
  352.     pScreen->CursorLimits = qvCursorLimits;
  353.     pScreen->PointerNonInterestBox = qvPointerNonInterestBox;
  354.     pScreen->ConstrainCursor = qvConstrainCursor;
  355.     pScreen->RecolorCursor = miRecolorCursor;
  356.  
  357. #ifdef ULTRIX3_0
  358.     if (isSMdevice)
  359.     retval = mfbScreenInit(pScreen, smInfo->bitmap, 
  360.                    1024, 864, i, i, 1024);
  361.     else
  362. #endif
  363.     retval = mfbScreenInit(pScreen, qvInfo->bitmap, 
  364.                    1024, 864, i, i, 1024);
  365.     if (!retval)
  366.     {
  367.     close(fdQVSS);
  368.     return FALSE;
  369.     }
  370.     /*
  371.      * qvQueryBestSize gives hints for cursors, as well as
  372.      * for pixmaps and tiles, mash the mfb supplied version
  373.      */
  374.     pScreen->QueryBestSize = qvQueryBestSize;
  375.     /*
  376.      * wrap screen close routine with our own
  377.      */
  378.     CloseScreen = pScreen->CloseScreen;
  379.     pScreen->CloseScreen = qvssScreenClose;
  380.     /*
  381.      * create and install the default colormap
  382.      */
  383.     if (!mfbCreateDefColormap (pScreen))
  384.     {
  385.     close (fdQVSS);
  386.     return FALSE;
  387.     }
  388.     return TRUE;
  389. }
  390.  
  391. /* ARGSUSED */
  392. int
  393. qvssMouseProc(pDev, onoff, argc, argv)
  394.     DevicePtr pDev;
  395.     int onoff, argc;
  396.     char *argv[];
  397. {
  398.     BYTE map[4];
  399.  
  400.     switch (onoff)
  401.     {
  402.     case DEVICE_INIT: 
  403.         qvPointer = pDev;
  404.         pDev->devicePrivate = (pointer) &queue;
  405.         map[1] = 1;
  406.         map[2] = 2;
  407.         map[3] = 3;
  408.         InitPointerDeviceStruct(
  409.         qvPointer, map, 3, qvGetMotionEvents, qvChangePointerControl,
  410.         0);
  411.         SetInputCheck(&queue->head, &queue->tail);
  412.         break;
  413.     case DEVICE_ON: 
  414.         pDev->on = TRUE;
  415.             hotX = hotY = 0;
  416.         AddEnabledDevice(fdQVSS);
  417.         break;
  418.     case DEVICE_OFF: 
  419.         pDev->on = FALSE;
  420. /*    RemoveEnabledDevice(fdQVSS);   */
  421.         break;
  422.     case DEVICE_CLOSE: 
  423.         break;
  424.     }
  425.     return Success;
  426.  
  427. }
  428.  
  429. #define LK_REPEAT_ON  0xe3
  430. #define LK_REPEAT_OFF 0xe1
  431.  
  432. int
  433. SetLKAutoRepeat (onoff)
  434.     Bool onoff;
  435. {
  436.     extern char *AutoRepeatLKMode();
  437.     extern char *UpDownLKMode();
  438.     
  439.     struct qv_kpcmd ioc; 
  440.     register char  *divsets;
  441.     divsets = onoff ? (char *) AutoRepeatLKMode() : (char *) UpDownLKMode();
  442.  
  443.     ioc.nbytes = 0;
  444.     while (ioc.cmd = *divsets++)
  445.     ioctl(fdQVSS, QIOCKPCMD, (char *)&ioc);
  446.     ioc.cmd = ((onoff > 0) ? LK_REPEAT_ON : LK_REPEAT_OFF);
  447.     return(ioctl(fdQVSS, QIOCKPCMD, (char *)&ioc));
  448.  
  449. }
  450.  
  451. /* ARGSUSED */
  452. int
  453. qvssKeybdProc(pDev, onoff, argc, argv)
  454.     DevicePtr pDev;
  455.     int onoff, argc;
  456.     char *argv[];
  457. {
  458.     KeySymsRec keySyms;
  459.     CARD8 modMap[MAP_LENGTH];
  460.  
  461.     switch (onoff)
  462.     {
  463.     case DEVICE_INIT: 
  464.         qvKeyboard = pDev;
  465.         pDev->devicePrivate = (pointer) & queue;
  466.         if (!GetLK201Mappings( &keySyms, modMap))
  467.         return BadAlloc;
  468.         InitKeyboardDeviceStruct(
  469.             qvKeyboard, &keySyms, modMap, qvBell,
  470.             qvChangeKeyboardControl);
  471.             xfree(keySyms.map);
  472. /*        SetLKAutoRepeat(FALSE); */
  473.         break;
  474.     case DEVICE_ON: 
  475.         pDev->on = TRUE;
  476.         AddEnabledDevice(fdQVSS);
  477.         break;
  478.     case DEVICE_OFF: 
  479.         pDev->on = FALSE;
  480. /*        RemoveEnabledDevice(fdQVSS);  */
  481.         break;
  482.     case DEVICE_CLOSE: 
  483.         break;
  484.     }
  485.     return Success;
  486. }
  487.  
  488.  
  489. /*****************
  490.  * ProcessInputEvents:
  491.  *    processes all the pending input events
  492.  *****************/
  493.  
  494. extern int screenIsSaved;
  495.  
  496. void
  497. ProcessInputEvents()
  498. {
  499. #define DEVICE_KEYBOARD 2
  500.     register int    i;
  501.     register    vsEvent * pE;
  502.     xEvent    x;
  503.     int     nowInCentiSecs, nowInMilliSecs, adjustCentiSecs;
  504.     struct timeval  tp;
  505.     int     needTime = 1;
  506. #ifndef NO_EVENT_COMPRESSION
  507.     int j;
  508. #endif
  509.  
  510.     i = queue->head;
  511.     while (i != queue->tail)
  512.     {
  513.     if (screenIsSaved == SCREEN_SAVER_ON)
  514.         SaveScreens(SCREEN_SAVER_OFF, ScreenSaverReset);
  515.     pE = &queue->events[i];
  516.     x.u.keyButtonPointer.rootX = pE->vse_x + hotX;
  517.     x.u.keyButtonPointer.rootY = pE->vse_y + hotY;
  518.     if (sizeof(pE->vse_time) == 4)
  519.         x.u.keyButtonPointer.time = lastEventTime = pE->vse_time;
  520.     else {
  521.         /* 
  522.          * The following silly looking code is because the old version of the
  523.          * driver only delivers 16 bits worth of centiseconds. We are supposed
  524.          * to be keeping time in terms of 32 bits of milliseconds.
  525.          */
  526.         if (needTime)
  527.         {
  528.         needTime = 0;
  529.         gettimeofday(&tp, 0);
  530.         nowInCentiSecs = ((tp.tv_sec * 100) + (tp.tv_usec / 10000)) & 0xFFFF;
  531.         /* same as driver */
  532.         nowInMilliSecs = (tp.tv_sec * 1000) + (tp.tv_usec / 1000);
  533.         /* beware overflow */
  534.         }
  535.         if ((adjustCentiSecs = nowInCentiSecs - pE->vse_time) < -20000)
  536.         adjustCentiSecs += 0x10000;
  537.         else
  538.         if (adjustCentiSecs > 20000)
  539.             adjustCentiSecs -= 0x10000;
  540.         x.u.keyButtonPointer.time = lastEventTime =
  541.         nowInMilliSecs - adjustCentiSecs * 10;
  542.     }
  543.  
  544. #ifdef ULTRIX3_0
  545.     if (isSMdevice) {
  546.     if ((pE->type != MOTION_TYPE) &&
  547.         (pE->device == KEYBOARD_DEVICE))
  548.     {
  549.         x.u.u.detail = pE->key;
  550.         switch (pE->type)
  551.         {
  552.         case BUTTON_DOWN_TYPE: 
  553.             x.u.u.type = KeyPress;
  554.             (*qvKeyboard->processInputProc)(&x, qvKeyboard, 1);
  555.             break;
  556.         case BUTTON_UP_TYPE: 
  557.             x.u.u.type = KeyRelease;
  558.             (*qvKeyboard->processInputProc)(&x, qvKeyboard, 1);
  559.             break;
  560.         case BUTTON_RAW_TYPE:
  561.             ProcessLK201Input(&x, qvKeyboard);
  562.         }
  563.     }
  564.     else
  565.     {
  566.         if (pE->type != MOTION_TYPE)
  567.         {
  568.         if (pE->type == BUTTON_DOWN_TYPE)
  569.             x.u.u.type = ButtonPress;
  570.         else
  571.             x.u.u.type = ButtonRelease;
  572.         /* mouse buttons numbered from one */
  573.         x.u.u.detail = pE->key;
  574.         }
  575.         else {
  576.         /* tell the server that the mouse moved */
  577.         x.u.u.type = MotionNotify;
  578.         }
  579.         (*qvPointer->processInputProc)(&x, qvPointer, 1);
  580.     }
  581.     }
  582.     else
  583. #endif
  584.     {
  585.     if ((pE->vse_type == VSE_BUTTON) &&
  586.         (pE->vse_device == DEVICE_KEYBOARD))
  587.     {                    /* better be a button */
  588.         x.u.u.detail = pE->vse_key;
  589.         switch (pE->vse_direction)
  590.         {
  591.         case VSE_KBTDOWN: 
  592.             x.u.u.type = KeyPress;
  593.             (*qvKeyboard->processInputProc)(&x, qvKeyboard, 1);
  594.             break;
  595.         case VSE_KBTUP: 
  596.             x.u.u.type = KeyRelease;
  597.             (*qvKeyboard->processInputProc)(&x, qvKeyboard, 1);
  598.             break;
  599.         default:            /* hopefully BUTTON_RAW_TYPE */
  600.             ProcessLK201Input(&x, qvKeyboard);
  601.         }
  602.     }
  603.     else
  604.     {
  605.         if (pE->vse_type == VSE_BUTTON)
  606.         {
  607.         if (pE->vse_direction == VSE_KBTDOWN)
  608.             x.u.u.type = ButtonPress;
  609.         else
  610.             x.u.u.type = ButtonRelease;
  611.         /* mouse buttons numbered from one */
  612.         x.u.u.detail = pE->vse_key + 1;
  613.         }
  614.         else {
  615. #ifndef NO_EVENT_COMPRESSION
  616.         j = (i == qLimit) ? 0 : i + 1;
  617.         /*
  618.          * to get here we knew that 
  619.          *
  620.          *     (vse_type != VSE_BUTTON || 
  621.          *      vse_device != DEVICE_KEYBOARD) && 
  622.          *     (vse_type != VSE_BUTTON)
  623.          *
  624.          * which means that for the next event to be a mouse
  625.          * motion, it must satisfy vse_type != VSE_BUTTON
  626.                  *
  627.                  * XXX -- We should implement motion history since we are 
  628.                  * throwing device events away....
  629.          */
  630.         if (j != queue->tail &&
  631.             queue->events[j].vse_type != VSE_BUTTON)
  632.           goto next;        /* sometimes the dragon wins */
  633.  
  634. #endif
  635.         /* tell the server that the mouse moved */
  636.         x.u.u.type = MotionNotify;
  637.         }
  638.     (*qvPointer->processInputProc)(&x, qvPointer, 1);
  639.     }
  640.     }
  641.  
  642.       next:
  643.     if (i == qLimit)
  644.         i = queue->head = 0;
  645.     else
  646.         i = ++queue->head;
  647.     }
  648. #undef DEVICE_KEYBOARD
  649. }
  650.  
  651. TimeSinceLastInputEvent()
  652. {
  653.     if (lastEventTime == 0)
  654.     lastEventTime = GetTimeInMillis();
  655.     return GetTimeInMillis() - lastEventTime;
  656. }
  657.  
  658. /* ARGSUSED */
  659. static void
  660. qvBell(loud, pDevice)
  661.     int loud;
  662.     DevicePtr pDevice;
  663. {
  664. #define LK_ENABLE_BELL 0x23    /* enable bell / set volume     */
  665.     struct qv_kpcmd ioc;
  666.  
  667. /* the lk201 volume is between 7 (quiet but audible) and 0 (loud) */
  668.     loud = 7 - ((loud / 14) & 7);
  669.     ioc.nbytes = 1;
  670.     ioc.cmd = LK_ENABLE_BELL;
  671.     ioc.par[0] = loud;
  672.     ioctl(fdQVSS, QIOCKPCMD, (char *)&ioc);
  673.  
  674.     ioc.nbytes = 0;
  675.     ioc.cmd = LK_RING_BELL;
  676.     ioctl(fdQVSS, QIOCKPCMD, (char *)&ioc);
  677. }
  678.  
  679. static void
  680. ChangeLED(led, on)
  681.     int led;
  682.     Bool on;
  683. {
  684.     struct qv_kpcmd ioc;
  685.  
  686.     switch (led) {
  687.        case 1:
  688.       ioc.par[0] = LED_1;
  689.       break;
  690.        case 2:
  691.           ioc.par[0] = LED_2;
  692.       break;
  693.        case 3:
  694.           /* the keyboard's LED_3 is the Lock LED, which the server owns.
  695.              So the user's LED #3 maps to the keyboard's LED_4. */
  696.           ioc.par[0] = LED_4;
  697.       break;
  698.        default:
  699.       return;   /* out-of-range LED value */
  700.       }
  701.  
  702.     ioc.cmd = on ? LK_LED_ENABLE : LK_LED_DISABLE;
  703.     ioc.par[1] = 0;
  704.     ioc.nbytes = 1;
  705.     ioctl(fdQVSS, QIOCKPCMD, (char *)&ioc);
  706. }
  707.  
  708. SetLockLED (on)
  709.     Bool on;
  710.     {
  711.     struct qv_kpcmd ioc;
  712.     ioc.cmd = on ? LK_LED_ENABLE : LK_LED_DISABLE;
  713.     ioc.par[0] = LED_3;
  714.     ioc.par[1] = 0;
  715.     ioc.nbytes = 1;
  716.     ioctl(fdQVSS, QIOCKPCMD, (char *)&ioc);
  717.     }
  718.  
  719. /* ARGSUSED */
  720. static void
  721. qvChangeKeyboardControl(pDevice, ctrl)
  722.     DevicePtr pDevice;
  723.     KeybdCtrl *ctrl;
  724. {
  725. #define LK_ENABLE_CLICK 0x1b    /* enable keyclick / set volume    */
  726. #define LK_DISABLE_CLICK 0x99    /* disable keyclick entirely    */
  727. #define LK_ENABLE_BELL 0x23    /* enable bell / set volume     */
  728.  
  729.     struct qv_kpcmd ioc;
  730.     int i;
  731.  
  732.     if (ctrl->click == 0)    /* turn click off */
  733.     {
  734.     ioc.nbytes = 0;
  735.     ioc.cmd = LK_DISABLE_CLICK;
  736.     ioctl(fdQVSS, QIOCKPCMD, (char *)&ioc);
  737.     }
  738.     else 
  739.     {
  740.         int volume;
  741.  
  742.         volume = 7 - ((ctrl->click / 14) & 7);
  743.     ioc.nbytes = 1;
  744.     ioc.cmd = LK_ENABLE_CLICK;
  745.     ioc.par[0] = volume;
  746.     ioctl(fdQVSS, QIOCKPCMD, (char *)&ioc);
  747.     }
  748.  
  749.     /* ctrl->bell: the DIX layer handles the base volume for the bell */
  750.     
  751.     /* ctrl->bell_pitch: as far as I can tell, you can't set this on lk201 */
  752.  
  753.     /* ctrl->bell_duration: as far as I can tell, you can't set this  */
  754.  
  755.     /* LEDs */
  756.     for (i=1; i<=MAX_LED; i++)
  757.         ChangeLED(i, (ctrl->leds & (1 << (i-1))) ? TRUE : FALSE);
  758.  
  759.     /* ctrl->autoRepeat: I'm turning it all on or all off.  */
  760.  
  761.     SetLKAutoRepeat(ctrl->autoRepeat);
  762. }
  763.  
  764. /* ARGSUSED */
  765. static void
  766. qvChangePointerControl(pDevice, ctrl)
  767.     DevicePtr pDevice;
  768.     PtrCtrl   *ctrl;
  769. {
  770. #ifdef ULTRIX3_0
  771.     if (isSMdevice)
  772.     {
  773.     smInfo->mthreshold = ctrl->threshold;
  774.     if (!(smInfo->mscale = ctrl->num / ctrl->den))
  775.         smInfo->mscale = 1;    /* watch for den > num */
  776.     }
  777.     else
  778. #endif
  779.     {
  780.     qvInfo->mthreshold = ctrl->threshold;
  781.     if (!(qvInfo->mscale = ctrl->num / ctrl->den))
  782.         qvInfo->mscale = 1;    /* watch for den > num */
  783.     }
  784. }
  785.  
  786. /* ARGSUSED */
  787. static int
  788. qvGetMotionEvents(buff, start, stop, pScr)
  789.     CARD32 start, stop;
  790.     xTimecoord *buff;
  791.     ScreenPtr pScr;
  792. {
  793.     return 0;
  794. }
  795.  
  796. /* ARGSUSED */
  797. static Bool
  798. qvSetCursorPosition( pScr, newx, newy, generateEvent)
  799.     ScreenPtr    pScr;
  800.     int    newx;
  801.     int    newy;
  802.     Bool        generateEvent;
  803. {
  804.     vsCursor    cursor;
  805.     xEvent    motion;
  806.     
  807.     cursor.x = newx - hotX;
  808.     cursor.y = newy - hotY;
  809.     if ( ioctl(fdQVSS, QIOCSMSTATE, (char *)&cursor) < 0)
  810.     {
  811.     ErrorF( "error warping cursor\n");
  812.     return FALSE;
  813.     }
  814.     if (generateEvent)
  815.     {
  816.     if (queue->head != queue->tail)
  817.         ProcessInputEvents();
  818.     motion.u.keyButtonPointer.rootX = newx;
  819.     motion.u.keyButtonPointer.rootY = newy;
  820.     motion.u.keyButtonPointer.time = lastEventTime;
  821.     motion.u.u.type = MotionNotify;
  822.     (*qvPointer->processInputProc) (&motion, qvPointer, 1);
  823.     }
  824.     return TRUE;
  825. }
  826.  
  827. static Bool
  828. qvDisplayCursor( pScr, pCurs)
  829.     ScreenPtr    pScr;
  830.     CursorPtr    pCurs;
  831. {
  832.     int i, x, y;
  833.  
  834.     /*
  835.      * load the cursor
  836.      */
  837.     if ((hotX != (int)pCurs->bits->xhot) || (hotY != (int)pCurs->bits->yhot))
  838.     {
  839.     x = mouse->x + hotX;
  840.     y = mouse->y + hotY;
  841.     hotX = pCurs->bits->xhot;
  842.     hotY = pCurs->bits->yhot;
  843.     qvSetCursorPosition(pScr, x, y, FALSE);
  844.     qvConstrainCursor(pScr, &constraintBox);
  845.     }
  846. #ifdef ULTRIX3_0
  847.     if (isSMdevice)
  848.     {
  849.     if ( ioctl (fdQVSS, QIOWCURSOR, (char *)((short *)pCurs->devPriv[ pScr->myNum]))
  850.         < 0)
  851.     {
  852.         ErrorF( "error writing cursor\n");
  853.         return FALSE;
  854.     }
  855. #ifdef notdef
  856.     for ( i=0; i<16; i++)
  857.         smInfo->cursorbits[i] = ((short *)pCurs->devPriv[ pScr->myNum])[i];
  858. #endif
  859.     }
  860.     else
  861. #endif
  862.     {
  863.     for ( i=0; i<16; i++)
  864.         qvInfo->cursorbits[i] = ((short *)pCurs->devPriv[ pScr->myNum])[i];
  865.     }
  866.     return TRUE;
  867. }
  868.  
  869.  
  870. /* ARGSUSED */
  871. static void
  872. qvPointerNonInterestBox( pScr, pBox)
  873.     ScreenPtr    pScr;
  874.     BoxPtr    pBox;
  875. {
  876.     mbox->bottom = pBox->y2;
  877.     mbox->top = pBox->y1;
  878.     mbox->left = pBox->x1;
  879.     mbox->right = pBox->x2;
  880. }
  881.  
  882. /* note that this driver does not support dealing with the minimums */
  883. /* ARGSUSED */
  884. static void
  885. qvConstrainCursor( pScr, pBox)
  886.     ScreenPtr    pScr;
  887.     BoxPtr    pBox;
  888. {
  889.     constraintBox = *pBox;
  890. #ifdef ULTRIX3_0
  891.     if (isSMdevice && smInfo)
  892.     {
  893.     smInfo->min_cur_x = pBox->x1 - hotX;
  894.     smInfo->min_cur_y = pBox->y1 - hotY;
  895.     smInfo->max_cur_x = pBox->x2 - hotX - 1;
  896.     smInfo->max_cur_y = pBox->y2 - hotY - 1;
  897.     } else
  898. #endif
  899.     if (qvInfo)
  900.     {
  901.     qvInfo->max_cur_x = pBox->x2 - hotX - 1;
  902.     qvInfo->max_cur_y = pBox->y2 - hotY - 1;
  903.     }
  904.     else
  905.     ErrorF( "qvConstrainCursor: info = %x\n", qvInfo);
  906. }
  907.  
  908. /*
  909.  * qv cursor top-left corner cannot go to negative coordinates,
  910.  * but sm can.
  911.  */
  912. /* ARGSUSED */static void
  913. qvCursorLimits( pScr, pCurs, pHotBox, pPhysBox)
  914.     ScreenPtr    pScr;
  915.     CursorPtr    pCurs;
  916.     BoxPtr    pHotBox;
  917.     BoxPtr    pPhysBox;    /* return value */
  918. {
  919. #ifdef ULTRIX3_0
  920.     if (isSMdevice)
  921.     {
  922.     pPhysBox->x1 = pHotBox->x1;
  923.     pPhysBox->y1 = pHotBox->y1;
  924.     }
  925.     else
  926. #endif
  927.     {    
  928.     pPhysBox->x1 = max( pHotBox->x1, (int)pCurs->bits->xhot);
  929.     pPhysBox->y1 = max( pHotBox->y1, (int)pCurs->bits->yhot);
  930.     }
  931.     pPhysBox->x2 = min( pHotBox->x2, 1024);
  932.     pPhysBox->y2 = min( pHotBox->y2, 864);
  933. }
  934.  
  935. static Bool
  936. qvRealizeCursor( pScr, pCurs)
  937.     ScreenPtr    pScr;
  938.     CursorPtr    pCurs;    /* a SERVER-DEPENDENT cursor */
  939. {
  940.     unsigned short red, green, blue;
  941.     int    forecolor, backcolor;
  942.     register short    *a, *b;    /* hardware-defined */
  943.     register int *    mask;    /* server-defined */
  944.     register int *    src;    /* server-defined */
  945.     register int    i;
  946.     int        cursorBytes = 32*sizeof(short);
  947.     int        lastRow = ((pCurs->bits->height < 16) ? pCurs->bits->height : 16);
  948.     register unsigned short widthmask = (1<<pCurs->bits->width)-1;
  949.                 /* used to mask off beyond the edge of the
  950.                    real mask and source bits
  951.                 */
  952.  
  953.     red = pCurs->foreRed;
  954.     green = pCurs->foreGreen;
  955.     blue = pCurs->foreBlue;
  956.     mfbResolveColor(&red, &green, &blue, (VisualPtr)NULL);
  957.     forecolor = red;
  958.     red = pCurs->backRed;
  959.     green = pCurs->backGreen;
  960.     blue = pCurs->backBlue;
  961.     mfbResolveColor(&red, &green, &blue, (VisualPtr)NULL);
  962.     backcolor = red;
  963.     pCurs->devPriv[ pScr->myNum] = (pointer)xalloc(cursorBytes);
  964.     if (!pCurs->devPriv[ pScr->myNum])
  965.     return FALSE;
  966.     bzero((char *)pCurs->devPriv[ pScr->myNum], cursorBytes);
  967.  
  968.     /*
  969.      * munge the SERVER-DEPENDENT, device-independent cursor bits into
  970.      * what the device wants, which is 32 contiguous shorts.
  971.      *
  972.      * cursor hardware has "A" and "B" bitmaps
  973.      * logic table is:
  974.      *
  975.      *        A    B    cursor
  976.      *
  977.      *        0    0    transparent
  978.      *        1    0    xor (not used)
  979.      *        0    1    black
  980.      *        1    1    white
  981.      */
  982.  
  983.     /*
  984.      * "a" bitmap = image 
  985.      *
  986.      * "b" bitmap can be same as "mask", providing "a" is never on when
  987.      *  "b" is off.
  988.      */
  989.     for ( i=0,
  990.       a = (short *)pCurs->devPriv[pScr->myNum],
  991.       b = ((short *)pCurs->devPriv[pScr->myNum]) + 16,
  992.     /* XXX assumes DIX pixmap pad is size of int, 
  993.        and cursor is < 32 bits wide
  994.     */
  995.       src = (int *)pCurs->bits->source,
  996.       mask = (int *)pCurs->bits->mask;
  997.  
  998.       i < lastRow;
  999.  
  1000.       i++, a++, b++, src++, mask++)
  1001.     {
  1002. #ifdef ULTRIX3_0
  1003.     if (isSMdevice)
  1004.         *a = (*src & forecolor) | ((*mask & ~*src) & backcolor);
  1005.     else
  1006. #endif
  1007.         *a = ((*src & backcolor) | (~*src & forecolor)) & *mask;
  1008.     *b = *mask;
  1009.     *a &= widthmask;
  1010.     *b &= widthmask;
  1011.     }
  1012.     return TRUE;
  1013. }
  1014.  
  1015. static Bool
  1016. qvUnrealizeCursor( pScr, pCurs)
  1017.     ScreenPtr    pScr;
  1018.     CursorPtr    pCurs;
  1019. {
  1020.     xfree(pCurs->devPriv[ pScr->myNum]);
  1021.     return TRUE;
  1022. }
  1023.  
  1024. static void
  1025. qvQueryBestSize(class, pwidth, pheight)
  1026. int class;
  1027. short *pwidth;
  1028. short *pheight;
  1029. {
  1030.     unsigned width, test;
  1031.  
  1032.     switch(class)
  1033.     {
  1034.       case CursorShape:
  1035.       *pwidth = 16;
  1036.       *pheight = 16;
  1037.       break;
  1038.       case TileShape:
  1039.       case StippleShape:
  1040.       width = *pwidth;
  1041.       if (width != 0) {
  1042.           /* Return the closest power of two not less than width */
  1043.           test = 0x80000000;
  1044.           /* Find the highest 1 bit in the width given */
  1045.           while(!(test & width))
  1046.              test >>= 1;
  1047.           /* If their number is greater than that, bump up to the next
  1048.            *  power of two */
  1049.           if((test - 1) & width)
  1050.              test <<= 1;
  1051.           *pwidth = test;
  1052.       }
  1053.       /* We don't care what height they use */
  1054.       break;
  1055.     }
  1056. }
  1057.  
  1058. /* ARGSUSED */
  1059. void
  1060. qvResolveColor(pred, pgreen, pblue, pVisual)
  1061.     unsigned short    *pred, *pgreen, *pblue;
  1062.     VisualPtr        pVisual;
  1063. {
  1064.     /* Gets intensity from RGB.  If intensity is >= half, pick white, else
  1065.      * pick black.  This may well be more trouble than it's worth. */
  1066.     *pred = *pgreen = *pblue = 
  1067.         (((30L * *pred +
  1068.            59L * *pgreen +
  1069.            11L * *pblue) >> 8) >= (((1<<8)-1)*50)) ? ~0 : 0;
  1070. }
  1071.  
  1072. Bool
  1073. qvCreateColormap(pmap)
  1074.     ColormapPtr    pmap;
  1075. {
  1076.     unsigned short red, green, blue;
  1077.     unsigned long pix;
  1078.  
  1079.     /* this is a monochrome colormap, it only has two entries, just fill
  1080.      * them in by hand.  If it were a more complex static map, it would be
  1081.      * worth writing a for loop or three to initialize it */
  1082.     pix = 0;
  1083.     red = green = blue = 0;
  1084.     if (AllocColor(pmap, &red, &green, &blue, &pix, 0) != Success)
  1085.     return FALSE;
  1086.     pix = 0;
  1087.     red = green = blue = ~0;
  1088.     if (AllocColor(pmap, &red, &green, &blue, &pix, 0) != Success)
  1089.     return FALSE;
  1090.     return TRUE;
  1091. }
  1092.  
  1093. /* ARGSUSED */
  1094. void
  1095. qvDestroyColormap(pmap)
  1096.     ColormapPtr    pmap;
  1097. {
  1098. }
  1099.  
  1100. /*
  1101.  * DDX - specific abort routine.  Called by AbortServer().
  1102.  */
  1103. void
  1104. AbortDDX()
  1105. {
  1106. }
  1107.  
  1108. /* Called by GiveUp(). */
  1109. void
  1110. ddxGiveUp()
  1111. {
  1112. }
  1113.  
  1114. /*ARGSUSED*/
  1115. int
  1116. ddxProcessArgument (argc, argv, i)
  1117.     int    argc;
  1118.     char *argv[];
  1119.     int    i;
  1120. {
  1121.     return 0;
  1122. }
  1123.  
  1124. void
  1125. ddxUseMsg()
  1126. {
  1127.     ErrorF("-bp<:screen> color     BlackPixel for screen\n");
  1128.     ErrorF("-wp<:screen> color     WhitePixel for screen\n");
  1129. }
  1130.